﻿

using DocumentFormat.OpenXml.Spreadsheet;
using Furion.InstantMessaging;
using Microsoft.AspNetCore.SignalR;

namespace Admin.NET.Core.Service;

[MapHub("/sysChatHub")]
public class SysChatHubService : Hub, IDynamicApiController
{

    private readonly IHubContext<OnlineUserHub, IOnlineUserHub> _chatHubContext;

    public SysChatHubService(IHubContext<OnlineUserHub, IOnlineUserHub> chatHubContext) {
        _chatHubContext = chatHubContext;
    }

    // 存储在线用户信息
    private static readonly ConcurrentDictionary<string, UserConnection> OnlineUsers =  new ConcurrentDictionary<string, UserConnection>();

    //向全部用户发送消息
    [AllowAnonymous]
    public async Task SendMessage(string user, string message)
    {
        //public async Task SendMessage(string user, string message)

        await Clients.All.SendAsync("ReceiveMessage", user, message);

        //----------------------------2. 条件性全局广播------------------------------
        //向除指定连接ID外的所有客户端发送消息。适用于需要排除特定连接（如发送者自身）的场景：

        await Clients.AllExcept(new[] { Context.ConnectionId }).SendAsync("UpdateData");
        //----------------------------3. 定向单客户端通信------------------------------
        //通过连接ID定位单个客户端，常用于私聊或定向控制：
        var connectionId = "";
        await Clients.Client(connectionId).SendAsync("PrivateAlert", "Your session expires soon");
        //批量向多个连接ID的客户端发送消息，适用于多设备同步场景：
        //await Clients.Clients(activeConnections).SendAsync("SyncState", data); 


        //----------------------------4. 组管理功能------------------------------
        //向指定组内的所有成员广播消息（需先调用 Groups.AddToGroupAsync 添加组）：
        //await Clients.Group("Admins").SendAsync("NewTicket", ticket);
        //同时向多个组发送消息，如跨频道通知：
        await Clients.Groups(new[] { "GroupA", "GroupB" }).SendAsync("CrossGroupEvent");
        //- GroupExcept 向组内除指定连接外的成员发送消息，适用于组内部分成员排除：
        //await Clients.GroupExcept("Team", excludedIds).SendAsync("TeamUpdate");

        //----------------------------5. 用户级消息路由------------------------------
        //通过用户ID（如ASP.NET Core Identity的UserId）向该用户的所有连接设备发送消息：
        //await Clients.User(userId).SendAsync("Notification", "You have a new message");

        //批量向多个用户的所有连接发送消息，适用于多用户系统通知：
        //await Clients.Users(userIds).SendAsync("SystemMaintenance", "Service will restart");



        //await _chatHubContext.Clients.All.ReceiveMessage(new MessageInput { 
        //Message = message,
        //SendUserId = user
        //});
    }


    // 用户登录
    public async Task Login(string username)
    {
        // 创建新用户连接信息
        var user = new UserConnection
        {
            ConnectionId = Context.ConnectionId,
            Name = username
        };

        // 添加到在线用户列表 为了方便，所以只用一个静态字典存储，重启就没了，现实开发就用数据库
        OnlineUsers.TryAdd(Context.ConnectionId, user);

        // 通知所有客户端更新在线用户列表
        await Clients.All.SendAsync("UserListUpdated", OnlineUsers.Values.ToList());

        // 通知所有客户端有新用户加入
        await Clients.Others.SendAsync("UserJoined", username);

        Console.WriteLine($"{username} 已登录，ConnectionId: {Context.ConnectionId}");
    }


    // 用户登出
    public async Task Logout()
    {
        if (OnlineUsers.TryRemove(Context.ConnectionId, out var user)) //删除用户列表
        {
            // 字符串方法名调用方式
            await Clients.Others.SendAsync("UserLeft", user.Name);
            await Clients.All.SendAsync("UserListUpdated", OnlineUsers.Values.ToList());
            Console.WriteLine($"用户 {user.Name} 已登出");
        }
         Context.Abort();
    }



    // 发送公共消息
    public async Task SendPublicMessage(string message)
    {
        if (OnlineUsers.TryGetValue(Context.ConnectionId, out var user))
        {
            //向除指定连接ID外的所有客户端发送消息。适用于需要排除特定连接（如发送者自身）的场景：
            await Clients.AllExcept(Context.ConnectionId).SendAsync("ReceiveMessage", user.Name, message);
        }

        // 向发送者返回确认
        await Clients.Caller.SendAsync("MessageProcessed", "消息已处理");

    }

    // 发送私聊消息
    public async Task SendPrivateMessage(string receiverConnectionId, string message)
    {
        if (OnlineUsers.TryGetValue(Context.ConnectionId, out var sender))
        {
            // 发送消息给接收者
            await Clients.Client(receiverConnectionId).SendAsync(
                "ReceivePrivateMessage",
                sender.Name,
                message
            );

            // 可选：发送消息给自己，这样发送者也能看到自己发送的消息
            // await Clients.Caller.SendAsync("ReceivePrivateMessage", "我", message);
        }
    }

    // 获取在线用户列表
    public async Task GetOnlineUsers()
    {
        if (OnlineUsers.TryGetValue(Context.ConnectionId, out var currentUser))
        {
            // 排除当前用户自己
            var users = OnlineUsers.Values
                .Where(u => u.ConnectionId != Context.ConnectionId)
                .ToList();

            await Clients.Caller.SendAsync("UserListUpdated", users);
        }
    }

    // 客户端断开连接时触发
    public override async Task OnDisconnectedAsync(Exception exception)
    {
        // 从在线用户列表中移除
        if (OnlineUsers.TryRemove(Context.ConnectionId, out var user))
        {
            // 更新所有客户端的在线用户列表
            await Clients.All.SendAsync("UserListUpdated", OnlineUsers.Values.ToList());

            // 通知所有客户端有用户离开
            await Clients.Others.SendAsync("UserLeft", user.Name);

            Console.WriteLine($"{user.Name} 已断开连接，ConnectionId: {Context.ConnectionId}");
        }

        await base.OnDisconnectedAsync(exception);
    }


    // 加入组
    public async Task JoinGroup(string groupName)
    {
        await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
        await Clients.Group(groupName).SendAsync("ReceiveMessage", $"用户 {Context.ConnectionId} 加入群组");
    }

    // 离开组
    public async Task LeaveGroup(string groupName)
    {
        await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
        await Clients.Group(groupName).SendAsync("ReceiveMessage", $"用户 {Context.ConnectionId} 离开群组");
    }



    // 客户端调用此方法发送消息并等待服务器处理结果（双向）
    public async Task<MessageResult> ProcessMessage(string user, string message, int priority)
    {
        // 模拟消息处理
        await Task.Delay(1000); // 模拟处理耗时

        var result = new MessageResult
        {
            Success = true,
            MessageId = Guid.NewGuid().ToString(),
            ProcessTime = DateTime.UtcNow,
            Priority = priority,
            Summary = $"消息[{message}]已由{user}发送，优先级{priority}"
        };

        // 使用扩展方法向发送者返回结果（双向）
        return result;
    }

    // 服务器主动调用特定客户端方法并等待响应（双向）
    public async Task<string> QueryClientStatus(string connectionId, string queryType)
    {
        // 使用扩展方法调用指定客户端的方法（支持多参数）
        return await Clients.Client(connectionId).InvokeAsync<string>(
            "GetClientStatus", queryType, CancellationToken.None);
    }

}



// 用户连接信息类
public class UserConnection
{
    public string ConnectionId { get; set; }
    public string Name { get; set; }
}


public class MessageResult
{
    public bool Success { get; set; }
    public string MessageId { get; set; }
    public DateTime ProcessTime { get; set; }
    public int Priority { get; set; }
    public string Summary { get; set; }
}